<template>
	<view class="container">
		<!-- 滚动区域 -->
		<view class="list-box" id="scroll-panel">
			<view class="left">
				<scroll-view scroll-y="true" :style="{ height: scrollHeight + 'px' }" :scroll-into-view="leftIntoView">
					<view class="item" v-for="(item, index) in leftArray" :key="index"
						:class="{ active: index == leftIndex }" :id="'left-' + index" @tap="leftTap(index)">
						{{ item.name }}
					</view>
				</scroll-view>
			</view>
			<view class="main">
				<scroll-view scroll-y="true" :style="{ height: scrollHeight + 'px' }" @scroll="mainScroll"
					:scroll-into-view="scrollInto" scroll-with-animation="true">
					<view class="item main-item" v-for="(item, index) in mainArray" :key="index" :id="'item-' + index">
						<view class="title">
							<view>{{ item.title }}</view>
						</view>
						<view class="goods" v-for="(item2, index2) in item.children" :key="index2">
							<image :src="item2.avatar" mode=""></image>
							<view class="goods-info">
								<view>每日情话第{{ index2 + 1 }}句</view>
								<view class="describe">{{ item2.describe }}</view>
								<view class="money">￥500 元</view>
							</view>
						</view>
					</view>
					<view class="fill-last" :style="{ height: fillHeight + 'px' }"></view>
				</scroll-view>
			</view>
		</view>
	</view>
</template>

<script>
import { getAvatar, getLove } from '@/api/type/type';
export default {
	data() {
		return {
			scrollHeight: 400,// 滚动容器的高度
			scrollTopSize: 0,// 滚动容器离顶部的距离
			fillHeight: 0, // 填充高度，用于最后一项低于滚动区域时使用
			leftArray: [],
			mainArray: [],
			topArr: [],
			leftIndex: 0,
			scrollInto: ''
		};
	},
	computed: {
		/* 计算左侧滚动位置定位 */
		leftIntoView() {
			return `left-${this.leftIndex > 3 ? this.leftIndex - 3 : 0}`;
		}
	},
	mounted() {
		/* 等待DOM挂载完成 */
		this.$nextTick(() => {
			/* 在非H5平台，nextTick回调后有概率获取到错误的元素高度，则添加200ms的延迟来减少BUG的产生 */
			setTimeout(() => {
				/* 等待滚动区域初始化完成 */
				this.initScrollView().then(() => {
					/* 获取列表数据，你的代码从此处开始 */
					this.getListData();
				});
			}, 200);
		});
	},
	methods: {
		/* 初始化滚动区域 */
		initScrollView() {
			return new Promise((resolve, reject) => {
				let view = uni.createSelectorQuery().in(this).select('#scroll-panel');
				view.boundingClientRect((res) => {
					this.scrollTopSize = res.top; // 滚动容器离顶部的距离
					this.scrollHeight = res.height; // 滚动容器的高度
					this.$nextTick(() => {
						resolve();
					});
				}).exec();
			});
		},
		/* 获取列表数据 */
		async getListData() {
			const res = await new Promise((resolve, reject) => {
				uni.showLoading();
				setTimeout(async () => {
					let list = [
						{ name: '宠物', title: '宠物列表', children: [] },
						{ name: '家具', title: '家具列表', children: [] },
						{ name: '家电', title: '家电列表', children: [] },
						{ name: '服饰', title: '服饰列表', children: [] },
						{ name: '鞋子', title: '鞋子列表', children: [] },
						{ name: '箱包', title: '箱包列表', children: [] },
						{ name: '母婴', title: '母婴列表', children: [] },
						{ name: '美妆', title: '美妆列表', children: [] },
						{ name: '运动', title: '运动列表', children: [] },
						{ name: '数码', title: '数码列表', children: [] }
					];
					let res = []
					for (let i = 0; i < 5; i++) {
						const { avatar } = await getAvatar({ type: 'json' });
						const { ishan } = await getLove({ type: 'json' });
						res.push({
							avatar: avatar,
							title: `第${i + 1}个商品标题`,
							describe: ishan,
						})
					}
					list.forEach((el) => {
						el.children = res
					})
					resolve({ list });
				}, 1000);
			})
			uni.hideLoading();
			uni.stopPullDownRefresh()
			this.leftArray = res.list;
			this.mainArray = res.list;
			// DOM 挂载后 再调用 getElementTop 获取高度的方法。
			this.$nextTick(() => {
				this.getElementTop();
			});
		},
		/* 获取元素顶部信息 */
		async getElementTop() {
			const res = await new Promise((resolve, reject) => {
				// 获取所有主区域元素
				let view = uni.createSelectorQuery().selectAll('.main-item');
				view.boundingClientRect((data) => {
					resolve(data);
				}).exec();
			})
			let topArr = res.map((item) => {
				return item.top - this.scrollTopSize; /* 减去滚动容器距离顶部的距离 */
			});
			this.topArr = topArr;
			/* 获取最后一项的高度，设置填充高度。判断和填充时做了 +-20 的操作，是为了滚动时更好的定位 */
			let last = res[res.length - 1].height;
			if (last < this.scrollHeight) {// 最后一项高度小于滚动区域高度
				this.fillHeight = this.scrollHeight - last;// 填充高度 = 滚动区域高度 - 最后一项高度 
			}
		},
		/* 主区域滚动监听 */
		mainScroll(e) {
			let top = e.detail.scrollTop;
			let index = 0;
			/* 查找当前滚动距离 */
			for (let i = this.topArr.length - 1; i >= 0; i--) {
				/* 在部分安卓设备上，因手机逻辑分辨率与rpx单位计算不是整数，滚动距离与有误差，增加2px来完善该问题 */
				if (top + 2 >= this.topArr[i]) {
					index = i;
					break;
				}
			}
			this.leftIndex = index < 0 ? 0 : index;
		},
		/* 左侧导航点击 */
		leftTap(index) {
			this.scrollInto = `item-${index}`;
		}
	}
};
</script>

<style lang="scss">
/* 容器 */
.container {
	height: 100%;
	background: #fff;
	// display: flex;
	// flex-direction: column;
	// flex-wrap: nowrap;
	// justify-content: flex-start;
	// align-items: flex-start;
	// align-content: flex-start;
	// .bottom-panel {
	// 	padding-bottom: 0;
	// 	padding-bottom: constant(safe-area-inset-bottom);
	// 	padding-bottom: env(safe-area-inset-bottom);
	// }
}

.list-box {
	height: 100%;
	display: flex;
	flex-wrap: nowrap;
	font-size: 28rpx;

	.left {
		width: 200rpx;
		background-color: #f6f6f6;
		line-height: 80rpx;
		font-size: 32rpx;

		.item {
			padding-left: 20rpx;
			position: relative;

			&:not(:first-child) {
				margin-top: 1px;

				&::after {
					content: '';
					display: block;
					height: 0;
					border-top: #d6d6d6 solid 2rpx;
					width: 100%;
					position: absolute;
					top: -2rpx;
					right: 0;
					transform: scaleY(0.5);
					/* 1px像素 */
				}
			}

			&.active {
				color: #42b983;
				background-color: #fff;
			}
		}

		.fill-last {
			height: 0;
			width: 100%;
			background: none;
		}
	}

	.main {
		background-color: #fff;
		padding-left: 20rpx;
		width: 0;
		flex-grow: 1;
		box-sizing: border-box;

		.title {
			line-height: 64rpx;
			font-size: 24rpx;
			font-weight: bold;
			color: #666;
			background-color: #fff;
			position: sticky;
			top: 0;
			z-index: 19;
		}

		.item {
			padding-bottom: 10rpx;
			border-bottom: #eee solid 1px;
		}

		.goods {
			display: flex;
			flex-direction: row;
			flex-wrap: nowrap;
			justify-content: flex-start;
			align-items: center;
			align-content: center;
			margin-bottom: 10rpx;

			&-info {
				width: calc(100% - 120rpx);
				padding: 0 10rpx;
				box-sizing: border-box;
			}

			&>image {
				width: 120rpx;
				height: 120rpx;
			}

			.describe {
				font-size: 24rpx;
				color: #999;
			}

			.money {
				font-size: 24rpx;
				color: #efba21;
			}
		}
	}
}
</style>
